#define E_I2C_MASTER
#include "H/I2C_MASTER.H"


/*****************************************************
*函数名称：void I2C_MASTER_INT()
*函数功能：I2C主机模式中断服务函数
*入口参数：void
*出口参数：void
*****************************************************/
void I2C_MASTER_INT()
{
    R_I2C_M_OVERTIME=0;
    if(CHECK_MASTER_I2CESTA())
    {
       //状态错误
       F_I2C_M_ERR=1; //通讯失败
       F_I2C_M=1;     //总线空闲
       I2C_M_STOP();
    }
    else
    {
       //状态正确          
        if(F_I2C_M_MODE)
        {
           //主机数据接收         
           R_I2C_M_DATA_LENGTH--;
           if(R_I2C_M_DATA_LENGTH==0)
           {               
                I2C_M_STOP();             
                F_I2C_M=1;     //总线空闲
                F_I2C_M_ERR=0; //通讯成功              
            } 
            *P_I2C_M_DATA++=I2CDAT; 
        }
        else
        {          
           //主机数据发送
            if(R_I2C_M_DATA_LENGTH==0)
            {
                I2C_M_STOP();
                F_I2C_M=1;     //总线空闲
                F_I2C_M_ERR=0; //通讯成功              
            } 
            else
            {
                I2CDAT=*P_I2C_M_DATA++; 
                R_I2C_M_DATA_LENGTH--;
            }                
        }                        
    }
}


/*****************************************************
*函数名称：void I2C_M_OVERTIME(uchar R_OVERTIME)
*函数功能：I2C超时判断，超时范围设置1~255，超时时间=调用时间*R_OVERTIME，超时重发数据
*入口参数：uchar R_OVERTIME 超时时间设置
*出口参数：void
*****************************************************/
void I2C_M_OVERTIME(uchar R_OVERTIME)
{
    if(F_I2C_M==0)  //总线忙
    {
        R_I2C_M_OVERTIME++;        //超时计数，与调用时间有关，需用户自行确认
        if(R_I2C_M_OVERTIME>=R_OVERTIME)
        {
            //超时，总线长时间未释放，I2C 关闭
            I2CCON0=I2CEN_DIS|I2CMOD(1)|I2CIE(1);//I2C不使能|主机模式|中断使能           
            F_I2C_M=1;      //1：总线空闲
            F_I2C_M_ERR=1;  //1：通讯失败 
            F_I2C_M_OVERTIME=1;//1：超时           
        }  
    }            
}

/*****************************************************
*函数名称：void I2C_MASTER_START(uchar R_ADDR,uchar *P_DATA,uchar R_LENGTH,bit F_MODE)
*函数功能：调用该函数则开始执行I2C主机模式收发
*入口参数：uchar R_ADDR    通讯地址0~0x7FH
           uchar *P_DATA  数据存储地址
           uchar R_LENGTH 通讯数据长度
           bit F_MODE    0：主机发送   1：主机接收
*出口参数：void
*****************************************************/
void I2C_MASTER_START(uchar R_ADDR,uchar *P_DATA,uchar R_LENGTH,bit F_MODE)
{    
    if(F_I2C_M)  //总线空闲
    {
        R_I2C_M_ADDR=R_ADDR;
        P_I2C_M_DATA=P_DATA;
        F_I2C_M_MODE=F_MODE;
        R_I2C_M_DATA_LENGTH=R_LENGTH;

        I2CCON0=I2CEN_EN|I2CMOD(1)|I2CIE(1);//I2C使能|主机模式|中断使能
        I2CDAT=I2CADR(R_I2C_M_ADDR)|F_I2C_M_MODE;//从机地址|主机发送
        I2C_M_START(); //发送起始位
        R_I2C_M_OVERTIME=0;
        F_I2C_M_OVERTIME=0;
        F_I2C_M=0;
    }
}
/*****************************************************
*函数名称：void I2C_MASTER_INIT(uint R_SPD)
*函数功能：I2C初始化,主机模式
*入口参数：uint R_SPD速率
*出口参数：void
*****************************************************/
void I2C_MASTER_INIT(uint R_SPD)
{
    uchar i=0;
    MAP0 &=~0x30;
    MAP0 |=I2CSDAM(D_M_SDA)|I2CSCLM(D_M_SCL);

  
    I2C_SDA_OUT;//SDA做输出口
    I2C_SCL_OUT;//SCL做输出口
    I2C_SDA=1;//SDA输出高电平
    I2C_SCL=1;//SCL输出高电平

    I2C_SCL_OD_ON; //SCL开漏使能
    I2C_SDA_OD_ON; //SDA开漏使能  

    //I2CSPD=RC32M/OSCD/I2CCLK(速率)
    #if     D_OSCD==1
    i=(32>>1)*1000L/R_SPD;
    #elif   D_OSCD==2
    i=(32>>2)*1000L/R_SPD;
    #elif   D_OSCD==3 
    i=(32>>3)*1000L/R_SPD;
    #elif   D_OSCD==4
    i=(32>>4)*1000L/R_SPD;
    #endif
    I2CSPD=i;
 
    F_I2C_M=1;//I2C总线空闲
    F_I2C_M_ERR=0;//通讯正常
    F_I2C_M_OVERTIME=0;//未超时
}
/*****************************************************
*函数名称：void I2C_M_START()
*函数功能：发送起始位
*入口参数：void
*出口参数：void
*****************************************************/
void I2C_M_START()
{ 
    I2CSTO = 0;
    I2CSTA = 1;
}

/*****************************************************
*函数名称：void I2C_M_STOP()
*函数功能：发送停止位
*入口参数：void
*出口参数：void
*****************************************************/
void I2C_M_STOP()
{
    I2CSTA = 0;
    I2CSTO = 1;
}
/*****************************************************
*函数名称：bit CHECK_MASTER_I2CESTA()
*函数功能：I2C错误状态返回，=1状态错误
*入口参数：void
*出口参数：void
*****************************************************/
bit CHECK_MASTER_I2CESTA()
{
    uchar R_I2CSTATE;
    R_I2CSTATE=I2CSTATE&0X07;
    F_I2C_M_STA=0;
    switch(R_I2CSTATE)
    {               
    case 1://主机模式下地址不匹配,从机回NACK         
    case 2://主机模式下发数据时,从机回NACK
        F_I2C_M_STA=1;
        break;
//    case 3://从机发送模式下，主机回NACK
//        F_I2C_ERR=1;
//        break;
    default : break;
    }
    return  F_I2C_M_STA;
}























